/**
 * SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
 * SPDX-License-Identifier: Mulan PSL v2
 */
<template>
    <div class="upload-file-page">
        <sf-alert class="upload-file__alert"
                  type="info"
                  :show-default-opr="false"
                  :closable="false"
                  :title="_('数据集的schema无法修改，上传的table文件必须能被现有的schema所兼容')"
                  :center="false"/>
        <div class="upload-file__warp">
            <div class="upload-file__form">
                <sf-form ref="basicForm" :label-width="200">
                    <sf-form-item>
                        <sf-fieldlabel style="padding-left: 0;" label-align="top">数据集类型</sf-fieldlabel>
                        <sf-radio-group v-model="datasetModal" class="radio-group" :is-space-group="true">
                            <sf-radio-button class="radio-group__item" check-value="table">{{ _('table') }}
                            </sf-radio-button>
                            <sf-radio-button class="radio-group__item" check-value="file">{{ _('其他') }}
                            </sf-radio-button>
                        </sf-radio-group>
                        <div style="font-size: 12px;line-height: 17px;color: #999999;margin-top: 8px;">
                            {{ isTable ? _('支持格式: csv') : _('可上传任意格式的文件，但平台不做文件内容解析') }}
                        </div>
                    </sf-form-item>
                    <sf-form-item>
                        <sf-fieldlabel label-align="top" show-required>上传文件</sf-fieldlabel>
                        <uploader v-show="isTable"
                                  ref="fileUploadTable"
                                  class="uploader-example"
                                  :options="uploadOption"
                                  :fileStatusText="fileStatusText"
                                  :autoStart="false"
                                  @file-success="onTableFileSuccess"
                                  @file-progress="onFileProgress"
                                  @file-error="onFileError"
                                  @file-added="onFileAdded"
                                  @file-removed="onFileRemoved">
                            <uploader-unsupport></uploader-unsupport>
                            <uploader-drop :class="{'upload-valid':uploadValid}" @click.native="uploadClick">
                                <uploader-btn ref="uploadBtnTable" :attrs="attrs"
                                              style="display: none"/>
                                <i style="margin:24px 0" class="sf-comp-iconfont icon-comp-upload-image"></i>
                                <p style="font-size: 14px;font-weight: normal;line-height: 22px;text-align: center;color: #1D2129;">
                                    点击或拖拽文件到此处上传</p>
                                <p style="font-size: 12px;font-weight: normal;line-height: 20px;text-align: center;color: #86909C;">
                                    {{ _('仅限csv文件类型，文件大小不超过2G') }}</p>
                            </uploader-drop>
                            <uploader-list>
                                <div slot-scope="props" class="file-panel">
                                    <ul class="file-list">
                                        <li
                                            v-for="file in props.fileList"
                                            :key="file.id"
                                            class="file-item">
                                            <uploader-file
                                                ref="files"
                                                :class="['file_' + file.id, customStatus]"
                                                :file="file"
                                                :list="true"
                                            ></uploader-file>
                                        </li>
                                        <div v-if="!props.fileList.length" class="no-file"
                                             :class="{'text-valid':uploadValid}">
                                            {{ uploadText }}
                                        </div>
                                    </ul>
                                </div>
                            </uploader-list>
                        </uploader>
                        <uploader v-show="!isTable"
                                  ref="fileUploadFile"
                                  class="uploader-example"
                                  :options="uploadOption"
                                  :fileStatusText="fileStatusText"
                                  :autoStart="false"
                                  @file-success="onFileFileSuccess"
                                  @file-progress="onFileProgress"
                                  @file-error="onFileError"
                                  @file-added="onFileAdded"
                                  @file-removed="onFileRemoved">
                            <uploader-unsupport></uploader-unsupport>
                            <uploader-drop :class="{'upload-valid':uploadValid}" @click.native="uploadClick">
                                <uploader-btn ref="uploadBtnFile" style="display: none"/>
                                <i style="margin:24px 0" class="sf-comp-iconfont icon-comp-upload-image"></i>
                                <p style="font-size: 14px;font-weight: normal;line-height: 22px;text-align: center;color: #1D2129;">
                                    点击或拖拽文件到此处上传</p>
                                <p style="font-size: 12px;font-weight: normal;line-height: 20px;text-align: center;color: #86909C;">
                                    {{ _('可上传任意格式的文件，但平台不做文件内容解析') }}</p>
                            </uploader-drop>
                            <uploader-list>
                                <div slot-scope="props" class="file-panel">
                                    <ul class="file-list">
                                        <li
                                            v-for="file in props.fileList"
                                            :key="file.id"
                                            class="file-item">
                                            <uploader-file
                                                ref="files"
                                                :class="['file_' + file.id, customStatus]"
                                                :file="file"
                                                :list="true"
                                            ></uploader-file>
                                        </li>
                                        <div v-if="!props.fileList.length" class="no-file "
                                             :class="{'text-valid':uploadValid}">
                                            {{ uploadText }}
                                        </div>
                                    </ul>
                                </div>
                            </uploader-list>
                        </uploader>
                    </sf-form-item>
                </sf-form>
                <div v-if="dataPreviews.length !== 0 && isTable" class="data-previews">
                    <sf-grid class="basic-grid" :default-height="324" :default-width="1210">
                        <sf-toolbar ref="toolbar">
                            <div style="display: flex;align-items: flex-end;" class="pull-left">
                                
                                <sf-button-primary v-if="dataPreviewsNO!==0"
                                                   style="height: 24px;color: #fff;margin-right: 16px;"
                                                   @click="dataPreviewsNO-=1">
                                    预览上一个
                                </sf-button-primary>
                                <sf-button-primary style="height: 24px;color: #fff; margin-right: 16px;"
                                                   @click="dataPreviewsNext">
                                    预览下一个
                                </sf-button-primary>
                                <span>{{ dataPreviewsNow.name }}的预览</span>
                            </div>
                            <div class="pull-right">
                                <span>数据编码格式：UTF-8</span>
                            </div>
                        </sf-toolbar>
                        <sf-table ref="table" :options="gridOptions" :default-width="1210" :default-height="260">
                            <sf-table-column v-for="item in dataPreviewsNow.column" :key="item" :data-index="item"
                                             :default-width="40">
                                {{ item }}
                            </sf-table-column>
                        </sf-table>
                        <sf-checkbox v-model="formData.csvHead" @change="checkboxChange">
                            <lang>将第一行解析为列标题</lang>
                        </sf-checkbox>
                    </sf-grid>
                </div>
            </div>
        </div>
        <div class="upload-file__footer">
            <sf-button-primary :loading="isLoading" @click="creatDataset">确认</sf-button-primary>
            <sf-button @click="onReturn">取消</sf-button>
        </div>
    </div>
</template>

<script>
import {v4} from 'uuid';
import {md5} from "src/util/fileMd5";

const MAX_SIZE = 2147483648; // 2GB
const CHUNK_SIZE = 100 * 1024 * 1024
export default {
    props: {
        dataset: {
            type: String,
            default: ''
        },
        dataspace: {
            type: String,
            default: ''
        },
    },
    data() {
        return {
            isLoading: false,
            attrs: {accept: '.csv'},
            uploadOption: {
                target: '/ai-datalake/api/v1/upload-datasets',
                testChunks: false,
                chunkSize: CHUNK_SIZE,
                processParams: (params, file) => {
                    return {
                        fileSize: params.totalSize,
                        chunkSize: params.chunkSize,
                        totalChunk: params.totalChunks,
                        currentChunk: params.chunkNumber,
                        md5: params.identifier,
                        filePath: params.filename,
                        ...file.params
                    }
                },
                query: (file) => {
                    return {
                        ...file.params
                    }
                }
            },
            fileStatusText: {
                success: '上传成功',
                error: '上传失败',
                uploading: '上传中',
                paused: '已暂停',
                waiting: '等待上传'
            },
            customStatus: '',
            datasetModal: 'table',
            uploadText: '暂无待上传文件',
            uploadValid: false,
            dataPreviews: [],
            dataPreviewsNO: 0,
            
            uuid: '',
            
            formData: {
                tableNames: [],
                fileNames: [],
                csvHead: true,
            },
            gridOptions: {
                data: [],
                selectionHide: true,
            },
        }
    },
    computed: {
        customParams() {
            return {
                tableName: this.isTable ? 'data_table' : '',
                transactionId: this.uuid,
                totalFile: 1,
                currentFile: 1,
                format: '',
                fileType: this.datasetModal,
            }
        },
        isTable() {
            return this.datasetModal === 'table';
        },
        dataPreviewsNow() {
            return this.dataPreviews[this.dataPreviewsNO]
        }
    },
    watch: {
        dataPreviewsNow: {
            handler() {
                this.$nextTick().then(() => {
                    this.$refs.table?.loadData(this.dataPreviewsNow.list || [])
                })
            },
            deep: true,
        }
    },
    mounted() {
        this.uuid = v4();
    },
    methods: {
        statusSet(id, status) {
            let statusMap = {
                md5: {
                    text: '校验MD5',
                    bgc: '#fff'
                }
            }
            this.customStatus = status
            this.$nextTick().then(() => {
                const statusTag = document.createElement('p')
                statusTag.className = `custom-status-${id} custom-status`
                statusTag.innerText = statusMap[status].text
                statusTag.style.backgroundColor = statusMap[status].bgc
                const statusWrap = document.querySelector(`.file_${id} .uploader-file-status`)
                statusWrap.appendChild(statusTag)
            })
        },
        
        statusRemove(id) {
            this.customStatus = ''
            this.$nextTick().then(() => {
                const statusTag = document.querySelector(`.custom-status-${id}`)
                statusTag.remove()
            })
        },
        
        async onFileAdded(file) {
            if (this.isTable) {
                const fileArr = file.name.split('.');
                const suffix = fileArr.pop();
                if (suffix !== 'csv') {
                    this.uploadValid = true;
                    this.uploadText = '请上传指定的文件格式'
                    file.ignored = true;
                    return false
                } // 类型判断
                if (file.size > MAX_SIZE) {
                    this.uploadValid = true;
                    this.uploadText = '上传文件大小超过最大限度'
                    file.ignored = true;
                    return false
                } // 文件大小判断
                if (this.$refs.fileUploadTable.fileList.filter(item => {
                    return !item.error
                }).length >= 5) {
                    this.$showErr('最多支持上传五个表格数据')
                    file.ignored = true;
                    return false
                } // 文件数量判断 TODO 有bug 一次选择多个上传会都上传成功
            }
            if ([...this.formData.tableNames, ...this.formData.fileNames].includes(file.name)) {
                
                this.$showErr('禁止上传同名文件')
                file.ignored = true;
                return false
            } // 同名文件判断
            this.uploadValid = false;
            this.uploadText = '暂无待上传文件'
            file.params = this.customParams
            this.statusSet(file.id, 'md5')
            file.pause();
            const fileMd5 = await md5(file.file, CHUNK_SIZE);
            file.uniqueIdentifier = fileMd5;
            file.resume();
            this.statusRemove(file.id)
        },
        
        async onFileRemoved(file) {
            const {success, msg} = await this.$ajax.delete('/ai-datalake/api/v2/datasets/record', {
                transactionId: this.uuid,
                filePath: file.name,
                fileType: this.datasetModal,
            })
            if (!success) {
                this.$showErr(msg)
                return;
            }
            if (this.isTable) {
                this.formData.tableNames = this.formData.tableNames.filter(item => {
                    return item !== file.name;
                })
                this.dataPreviews = this.dataPreviews.filter(item => {
                    return item.name !== file.name
                })
            } else {
                this.formData.fileNames = this.formData.fileNames.filter(item => {
                    return item !== file.name;
                })
            }
        },
        
        onTableFileSuccess(rootFile, file) {
            this.formData.tableNames.push(file.name)
            this.getFileData(file)
        },
        
        onFileFileSuccess(rootFile, file) {
            this.formData.fileNames.push(file.name)
        },
        
        onFileProgress(rootFile, file, chunk) {
            window.console.log(
                `上传中 ${file.name}，chunk：${chunk.startByte / 1024 / 1024} ~ ${
                    chunk.endByte / 1024 / 1024
                }`
            )
        },
        
        async getFileData(file, type = 'add') {
            const params = {
                transactionId: this.uuid,
                filePath: file.name,
                fileType: 'table',
                csvHead: this.formData.csvHead
            }
            const {data, success, msg} = await this.$ajax.post('/ai-datalake/api/v1/tables/parse', params)
            if (!success) {
                this.$showErr(msg)
                return
            }
            if (data.length <= 0) {
                return;
            }
            if (type === 'add') {
                this.dataPreviews.push({
                    name: file.name,
                    column: Object.keys(data[0]),
                    list: data
                });
            } else {
                this.dataPreviews = this.dataPreviews.map(item => {
                    return item.name === file.name ? {
                        ...item, column: Object.keys(data[0]),
                        list: data
                    } : item
                })
            }
        },
        
        uploadClick() {
            this.isTable ?
                this.$refs.uploadBtnTable?.$el.click() : this.$refs.uploadBtnFile?.$el.click()
        },
        
        onReturn() {
            this.$router.go(-1);
        },
        
        async creatDataset() {
            if (this.$refs.fileUploadFile.uploader.isUploading() || this.$refs.fileUploadTable.uploader.isUploading()) {
                this.$showErr('文件正在上传，无法提交');
                return
            }
            if ([...this.formData.fileNames, ...this.formData.tableNames].length <= 0) {
                this.uploadValid = true;
                this.uploadText = '请选择要上传的数据集文件'
                return
            }
            const params = {
                ...this.formData,
                dataspace: this.dataspace,
                dataset: this.dataset,
                label: '',
                description: '',
                transactionId: this.uuid,
                uploadType: 'second',
                format: this.formData.tableNames.at(-1)?.split('.')?.at(-1) || '',
            }
            this.isLoading = true;
            const {success, msg} = await this.$ajax.post('/ai-datalake/api/v1/submit-datasets', params)
            this.isLoading = false;
            if (!success) {
                this.$showErr(msg);
                return;
            }
            this.$ok('编辑成功')
            this.onReturn()
        },
        
        dataPreviewsNext() {
            if (this.dataPreviewsNO === this.dataPreviews.length - 1) {
                this.$showErr('已经是最后一个文件了')
                return;
            }
            this.dataPreviewsNO += 1
        },
        
        checkboxChange() {
            this.dataPreviews.forEach(item => {
                this.getFileData(item, 'update')
            })
        },
        
        onFileError(rootFile, file, response) {
            this.$showErr(JSON.parse(response).msg)
        },
        
    }
}
</script>

<style scoped lang="less">
.upload-file-page {
    height: 100%;
    position: relative;
    .upload-file__alert {
        margin-left: 20px;
        padding-left: 8px;;
    }
    
    .upload-file__warp {
        height: calc(100% - 116px);
        
        .upload-file__form {
            height: 100%;
            overflow: auto;
            padding: 16px 20px;
            
            .radio-group {
                .radio-group__item {
                    border-radius: 12px;
                    height: 24px;
                    
                    &:first-child {
                        margin-right: 16px;
                    }
                }
                
            }
            
            .uploader-example {
                width: 1210px;
                
                .upload-valid {
                    border: 1px solid #E34D59;
                }
                
                .uploader-list {
                    max-height: 160px;
                    overflow: auto;
                    
                    .file-panel {
                        .file-list {
                            padding-left: 0;
                            
                            .text-valid {
                                color: #E34D59;
                            }
                            
                            .file-item {
                                list-style-type: none;
                                display: flex;
                                
                                .uploader-file {
                                    flex: 1
                                }
                                
                                /deep/ .custom-status {
                                    position: absolute;
                                    top: 0;
                                    left: 0;
                                    right: 0;
                                    bottom: 0;
                                    z-index: 1;
                                }
                            }
                        }
                    }
                }
                
                .uploader-drop {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    cursor: pointer;
                }
                
                /deep/ .uploader-file-actions {
                    .uploader-file-remove {
                        display: block !important;
                    }
                }
            }
            
            .sfv-form {
                padding: 0;
            }
            
            .data-previews {
                /deep/ .sfv-table {
                    .sfv-table_body {
                        .sfv-table_row:first-child {
                            font-weight: bold;
                        }
                    }
                }
            }
        }
    }
    
    .upload-file__footer {
        width: calc(100% + 72px);
        height: 80px;
        background: #FFFFFF;
        box-shadow: 0px -2px 4px 0px rgba(0, 0, 0, 0.06);
        display: flex;
        align-items: center;
        position: absolute;
        left: -24px;
        
        .sfv-btn {
            height: 36px;
        }
        
        .sfv-btn:first-child {
            margin-left: 20px;
            margin-right: 12px;
        }
    }
}
</style>
